热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

中表|个子_在SpringBoot项目中集成TDengine,并通过SQL对数据进行增删改查

篇首语:本文由编程笔记#小编为大家整理,主要介绍了在SpringBoot项目中集成TDengine,并通过SQL对数据进行增删改查相关的知识,希望对你有一定的参考价值。在

篇首语:本文由编程笔记#小编为大家整理,主要介绍了在SpringBoot项目中集成TDengine,并通过SQL对数据进行增删改查相关的知识,希望对你有一定的参考价值。


在SpringBoot项目中集成TDengine,并通过SQL对数据进行增删改查

好久以前写的,忘记发了,补发下;


文章目录


  • 创建数据库SQL语句
    • 查看数据库

  • 删除数据库SQL语句
  • 创建demo数据库下的表
    • 查看表
    • 超级表(也称为:STable)
      • 超级表STable是什么
      • 超级表STable解决什么
      • 超级表怎么用
        • 创建超级表的子表



  • 插入数据
  • 查询数据
    • 查询超级表的所有数据
    • 查询t1子表的所有数据
    • 聚合查询和函数使用

  • 修改数据
  • 删除数据
  • 删除表
  • 注意点
    • 源码地址

  • 总结

本篇文章介绍SpringBoot项目集成TDengine后,如何通过MyBatis的mapper操作数据的增删改查,以及数据库,表的创建。

SpringBoot项目如何集成TDengine便不再进行介绍了,可以看上篇 TDengine从安装到与SpringBoot项目集成使用

本文章演示中TDengine的版本:2.4.0.0


创建数据库SQL语句

那么在SpringBoot中调用TDengine,其实和数据库为mysql时的调用是差不多的,不过是jdbc驱动变了而已。

下面是创建数据库的语句

create database if not exists demo;

通过该SQL语句,可以创建数据库名为demo的数据库(只有demo数据库不存在的时候才会进行创建)。


查看数据库

show databases;

通过该命令可以看到我们刚创建的数据库demo。


删除数据库SQL语句

drop database if exists demo;

该SQL语句的含义是:如果存在demo数据库,则进行删除


创建demo数据库下的表

创建表时有几个需要特别注意的点:


  • 任何一张表或超级表是属于一个库的,在创建表之前,必须先创建库。
  • 处于两个不同库的表是不能进行 JOIN 操作的。
  • 创建并插入记录、查询历史记录的时候,均需要指定时间戳。

create table if not exists demo.weather(ts timestamp, temperature float, humidity float);

该SQL语句是在demo数据库下创建了名为weather的表,其中列有ts、temperature、humidity,类型分表为:timestamp、float、float;

TDengine还可以创建超级表STable。


查看表

show tables;

注意,在执行这句之前,要先进入到数据库。例如:use demo


超级表(也称为:STable)


超级表STable是什么

STable是同一类型数据采集点的抽象,是同类型采集实例的集合,包含多张数据结构一样的子表。每个STable为其子表定义了表结构和一组标签:表结构即表中记录的数据列及其数据类型;标签名和数据类型由STable定义,标签值记录着每个子表的静态信息,用以对子表进行分组过滤。子表本质上就是普通的表,由一个时间戳主键和若干个数据列组成,每行记录着具体的数据,数据查询操作与普通表完全相同;但子表与普通表的区别在于每个子表从属于一张超级表,并带有一组由STable定义的标签值。每种类型的采集设备可以定义一个STable。数据模型定义表的每列数据的类型,如温度、压力、电压、电流、GPS实时位置等,而标签信息属于Meta Data,如采集设备的序列号、型号、位置等,是静态的,是表的元数据。用户在创建表(数据采集点)时指定STable(采集类型)外,还可以指定标签的值,也可事后增加或修改。


超级表STable解决什么

TDengine要求每个数据采集点单独建表。独立建表的模式能够避免写入过程中的同步加锁,因此能够极大地提升数据的插入/查询性能。但是独立建表意味着系统中表的数量与采集点的数量在同一个量级。如果采集点众多,将导致系统中表的数量也非常庞大,让应用对表的维护以及聚合、统计操作难度加大。为降低应用的开发难度,TDengine引入了超级表(Super Table, 简称为STable)的概念。


超级表怎么用

TDengine扩展标准SQL语法用于定义STable,使用关键词tags指定标签信息。

例如下面的SQL

create table if not exists demo.weather(ts timestamp, temperature float, humidity float) tags(location nchar(64), groupId int);

创建了一个demo数据库下的weather的超级表。其中列有ts、temperature、humidity,类型分表为:timestamp、float、float;

和普通创建方式不同,多了一串:tags(location nchar(64), groupId int)其中tags是关键字,这句表示:带有标签location和标签groupId,类型分别为:nchar(64)、int。

前面完整的SQL表示:
创建了一个名为weather的STable,带有标签location和标签groupId。

创建完STable后,我们并不能直接使用它,而需要创建STable的子表。


创建超级表的子表

假设地区有,4个:杭州余杭区、杭州西湖区、杭州萧山区、上海宝山区。城市分组id有2个:杭州为1,上海为2。

我们对每个地区进行建表:

create table if not exists demo.t1 using demo.weather tags('杭州余杭区', 1);
create table if not exists demo.t2 using demo.weather tags('杭州西湖区', 1);
create table if not exists demo.t3 using demo.weather tags('杭州萧山区', 1);
create table if not exists demo.t4 using demo.weather tags('上海宝山区', 2);

demo.weather为超级表,创建了t1、t2、t3、t4四个子表,也就是普通的Table。

创建超级表时,tags后跟的是列的定义,而此时tags跟的是列的值。例如:tags(‘上海宝山区’, 2);是指超级表的location列值为上海宝山区,groupId列的值为2。

以t1为例,它表示地区t1的数据,表结构完全由超级表weather定义,标签location=”杭州余杭区”表示地区是杭州余杭区, type=1表示城市分组id是1

然后可以看到四张子表和一个超级表。


插入数据

如果要插入数据,也不是对超级表进行操作,而是对子表进行操作。

下面分别向四张表t1,t2, t3, t4写入一条数据,写入语句如下:

insert into demo.t1 values ('2018-01-01 00:00:00.001', 6.1,8.0);
insert into demo.t2 values ('2018-01-01 00:00:00.002', 6.5,8.9);
insert into demo.t3 values ('2018-01-01 00:00:00.003', 6.8,7.9);
insert into demo.t4 values ('2018-01-01 00:00:00.004', 7.5,10.9);


查询数据

查询超级表的所有数据

先查询所有数据。

SELECT * FROM demo.weather;


查询t1子表的所有数据

SELECT * FROM demo.t1;


聚合查询和函数使用

在这里,我们要查询位于"杭州西湖区"和"上海宝山区"两个地区的平均温度avg(temperature)、平均湿度avg(humidity)、最高温度max(temperature)、最低温度min(temperature),并将结果按所处城市id(groupId)进行聚合。

SELECT AVG(temperature),AVG(humidity), MAX(temperature), MIN(temperature) FROM demo.weather WHERE location='杭州西湖区' or location='上海宝山区' GROUP BY groupId;


修改数据

我想修改t1表中地区为"杭州西湖区"的温度为10.10。一般来说,很少用到修改数据。但其实用法和MySQL区别很大。

我们先查询一下原来的温度值是多少,那么按照MySQL中的方式这样写

select * from demo.t1 where location='杭州西湖区';

执行之后,其实是查询不到的,直接会报错。

错误信息:DB error: invalid operation: filter on tag not supported for normal table (0.000592s)

也就是说,正常表是不支持标签值的操作。这是属于超级表的操作。

那么其实我们知道,"杭州西湖区"是超级表中地区标签的值,而t1就是为这个地区建的。所以,直接在超级表上查询即可。

也就是可以这样查询:

select * from demo.weather where location='杭州西湖区';

这样就不会报错了。

修改数据其实有个大坑,默认是不支持修改数据的。

例如,我通过标签值/时间戳修改数据时报错:

update demo.weather set temperature=10.1 where location='杭州西湖区';
update demo.weather set temperature=10.1 where ts='2018-01-01 00:00:00.002';

此语句是不行的。报错如下:

那么,需要怎么修改。

我试了一种方式,就是打开update参数开关。

建库时如果不指定 update 参数,则 update 默认为0,表示数据不可修改。
所以,我们删除库,重新来。 创建库,并指定update参数值为1,执行如下的SQL:

drop database if exists demo;
create database if not exists demo update 1;
create table if not exists demo.weather(ts timestamp, temperature float, humidity float) tags(location nchar(64), groupId int);
create table if not exists demo.t1 using demo.weather tags('杭州余杭区', 1);
create table if not exists demo.t2 using demo.weather tags('杭州西湖区', 1);
create table if not exists demo.t3 using demo.weather tags('杭州萧山区', 1);
create table if not exists demo.t4 using demo.weather tags('上海宝山区', 2);
insert into demo.t1 values ('2018-01-01 00:00:00.001', 6.1,8.0);
insert into demo.t2 values ('2018-01-01 00:00:00.002', 6.5,8.9);
insert into demo.t3 values ('2018-01-01 00:00:00.003', 6.8,7.9);
insert into demo.t4 values ('2018-01-01 00:00:00.004', 7.5,10.9);

此时,update已经修改为1;

然而我发现数据还是无法被更改。

update demo.t1 set temperature=10.1 where ts='2018-01-01 00:00:00.002';
update demo.weather set temperature=10.1 where ts='2018-01-01 00:00:00.002';

均进行了尝试。

最后发现,原来TDengine的删除不是通过update,而是通过insert关键字。

那么继续:修改t1表中地区为"杭州西湖区"的温度为10.10。

先查看现在的数据:

select * from demo.weather where location='杭州西湖区';

接下来是修改

insert into demo.t2 values ('2018-01-01 00:00:00.002', 10.10,8.9);

你会发现,原来的数据被新的数据覆盖了。这是因为在同一个子表下,如果时间戳一致,则新的数据之间覆盖旧的数据。

这是TDengine的一种机制。

所以,你会发现,时间戳是不可被修改的。


删除数据

TDengine也不支持删除数据。在数据库中有一个keep属性,建库时不指定 keep 参数,则 keep 默认为3650,表示数据存储10年,即 TDengine 具有数据自动清理机制。

有两种修改方式:


  • keep与days关联使用,两者之间有限制(keep不可小于days),KEEP 参数是指修改数据文件保存的天数,缺省值为 3650,取值范围 [days, 365000],必须大于或等于 days 参数值,days默认值为10;
  • 可通过配置文件(vi /etc/taos/taos.cfg)及建库选项的keep, days参数进行配置。

注意:不能删除数据!

只能设置keep的时间,让TDengine自动清除数据。

我本来是想着是不是插入一个10年前的数据,会自动就变成删除,结果发现,时间戳是keep时间以前的,无法被插入到数据库中。


删除表

例如,删除表weather,那么SQL为:

drop table demo.weather;

注意:超级表和普通的表都是这样删除。


注意点
  • TDengine 对 SQL 语句中的英文字符不区分大小写,自动转化为小写执行。因此用户大小写敏感的字符串及密码,需要使用单引号将字符串引起来。
  • 虽然 Binary 类型在底层存储上支持字节型的二进制字符,但不同编程语言对二进制数据的处理方式并不保证一致,因此建议在 Binary 类型中只存储 ASCII 可见字符,而避免存储不可见字符。多字节的数据,例如中文字符,则需要使用 nchar 类型进行保存。如果强行使用 Binary 类型保存中文字符,虽然有时也能正常读写,但并不带有字符集信息,很容易出现数据乱码甚至数据损坏等情况。
  • SQL语句中的数值类型将依据是否存在小数点,或使用科学计数法表示,来判断数值类型是否为整型或者浮点型,因此在使用时要注意相应类型越界的情况。例如,9999999999999999999会认为超过长整型的上边界而溢出,而9999999999999999999.0会被认为是有效的浮点数。

源码地址

本项目演示了在Java中创建数据库,创建表,查询单条数据,分页查询数据,修改数据,新增数据,批量新增数据等操作,更多的功能,大家可以再自行研究。

https://github.com/chenhaoxiang/springboot-tdengine-demo


总结

我在Issues看到2019年有人就提出过TDengine不能修改和删除数据,到现在可以修改数据了,但是删除数据还是不行,只能设置keep的时间,让TDengine自动清除数据。

不过修改数据通过insert修改数据,还真是不习惯。

在这里,希望TDengine还是要支持能update关键字修改(并且不局限于时间戳的方式),不能搞卡死时间戳修改数据的权限,甚至是删除数据的权限。因为谁也不敢保证数据一定准确无误,无法人工修正的话,这是一个比较致命的问题。


推荐阅读
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • MySQL多表数据库操作方法及子查询详解
    本文详细介绍了MySQL数据库的多表操作方法,包括增删改和单表查询,同时还解释了子查询的概念和用法。文章通过示例和步骤说明了如何进行数据的插入、删除和更新操作,以及如何执行单表查询和使用聚合函数进行统计。对于需要对MySQL数据库进行操作的读者来说,本文是一个非常实用的参考资料。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了在使用Laravel和sqlsrv连接到SQL Server 2016时,如何在插入查询中使用输出子句,并返回所需的值。同时讨论了使用CreatedOn字段返回最近创建的行的解决方法以及使用Eloquent模型创建后,值正确插入数据库但没有返回uniqueidentifier字段的问题。最后给出了一个示例代码。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • 获取时间的函数js代码,js获取时区代码
    本文目录一览:1、js获取服务器时间(动态)2 ... [详细]
  • MySQL 数据库基础学习 一、SQL的作用及分类 二、数据类型 三、存储引擎  (建库建表、数据插入等))
    MySQL 数据库基础学习 一、SQL的作用及分类 二、数据类型 三、存储引擎 (建库建表、数据插入等)) ... [详细]
  • java开发公众号,java自学网公众号
    本文目录一览:1、JAVA微信公众号开发回复消息能回复多条吗?具体怎么代码实现? ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 本文总结和分析了JDK核心源码(2)中lang包下的基础知识,包括常用的对象类型包和异常类型包。在对象类型包中,介绍了Object类、String类、StringBuilder类、StringBuffer类和基本元素的包装类。在异常类型包中,介绍了Throwable类、Error类型和Exception类型。这些基础知识对于理解和使用JDK核心源码具有重要意义。 ... [详细]
  • 使用Spring AOP实现切面编程的步骤和注意事项
    本文介绍了使用Spring AOP实现切面编程的步骤和注意事项。首先解释了@EnableAspectJAutoProxy、@Aspect、@Pointcut等注解的作用,并介绍了实现AOP功能的方法。然后详细介绍了创建切面、编写测试代码的过程,并展示了测试结果。接着讲解了关于环绕通知的使用方法,并修改了FirstTangent类以添加环绕通知方法。最后介绍了利用AOP拦截注解的方法,只需修改全局切入点即可实现。使用Spring AOP进行切面编程可以方便地实现对代码的增强和拦截。 ... [详细]
  • Python教学练习二Python1-12练习二一、判断季节用户输入月份,判断这个月是哪个季节?3,4,5月----春 ... [详细]
  • 从批量eml文件中提取附件的Python代码实现方法
    本文介绍了使用Python代码从批量eml文件中提取附件的实现方法,包括获取eml附件信息、递归文件夹下所有文件、创建目的文件夹等步骤。通过该方法可以方便地提取eml文件中的附件,并保存到指定的文件夹中。 ... [详细]
  • 第七课主要内容:多进程多线程FIFO,LIFO,优先队列线程局部变量进程与线程的选择线程池异步IO概念及twisted案例股票数据抓取 ... [详细]
author-avatar
低调浪漫0613
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有